module rw_ram
(
	input wire sys_clk,
	input wire sys_rst_n,
	inout wire [15:0] ctrl_sig_inner,
	inout wire [15:0] addr_sig_inner,
	inout wire [15:0] data_sig_inner,
	inout wire work_ok_inner,
	output wire [15:0] data_out
);

reg [15:0] addr_buf;
reg [15:0] data_buf;

reg wr_en;
reg wr_en_d1;
reg wr_en_d2;
reg rd_en;
reg rd_en_d1;
reg rd_en_d2;

reg [15:0] data_sig_represent;
reg work_ok_represent;
reg get_time;
reg get_time_d1;
reg write_time;
reg write_time_d1;

/***************************************
	在读写ram方面，对于写数据来说，写使能有效时，待写数据必要
到位。而对于读数据来说，在本项目里面，它是说，系统检测到rd_en信号
为1所在的时钟上升沿的下一个时钟上升沿， RAM IP 核的数据端口才会出现有效数据。
在本模块代码里，rd_en与get_time同时为1，而get_time的延时一个时钟周期的
节拍变量为get_time_d1。所以，本模块通过判断get_time_d1的值，来确定向
内部数据总线变量data_sig_inner的代理变量的非阻塞赋值的时机。
注意，在本系统中，由于我在生成RAM IP核时，将q输出变量的一个复选框给
取消了勾选，所以，才有本模块的RAM 读操作的时序。如果，没有取消那个关于
q输出变量的复选框，则我们需要在能够到get_time_d1为1的时钟上升沿的下一个
时钟上升沿来进行非阻塞赋值操作，以将RAM IP核的连接线网变量data_out非阻塞
赋值给data_sig_represent，以此将RAM 中的数据送到data_sig_inner上面。同时呢，
我们也会需要调整work_ok_inner的赋值时机，以使内部数据总线变量data_sig_inner
的有效时机与work_ok_inner的有效时机一致。
*****************************************/

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		write_time <= 1'b0;
	else if (ctrl_sig_inner[2] == 1'b1)
		write_time <= 1'b1;
	else
		write_time <= 1'b0;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		wr_en <= 1'b0;
	else if (write_time == 1'b1)
		wr_en <= 1'b1;
	else
		wr_en <= 1'b0;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		get_time <= 1'b0;
	else if (ctrl_sig_inner[3] == 1'b1)
		get_time <= 1'b1;
	else
		get_time <= 1'b0;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		rd_en <= 1'b0;
	else if (ctrl_sig_inner[3] == 1'b1)
		rd_en <= 1'b1;
	else
		rd_en <= 1'b0;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		write_time_d1 <= 1'b0;
	else
		write_time_d1 <= write_time;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		get_time_d1 <= 1'b0;
	end
	else
	begin
		get_time_d1 <= get_time;
	end

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		addr_buf <= 16'h0;
		data_buf <= 16'h0;
	end
	else if (ctrl_sig_inner[2] == 1'b1)	//内存写使能，地址信号与数据信号都需要缓存。
	begin
		addr_buf <= addr_sig_inner;
		data_buf <= data_sig_inner;
	end
	else if (ctrl_sig_inner[3] == 1'b1)	//内存读使能，仅缓存地址信号。
	begin
		addr_buf <= addr_sig_inner;
		data_buf <= data_buf;
	end
	else
	begin
		addr_buf <= addr_buf;
		data_buf <= data_buf;
	end

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		data_sig_represent <= 16'hz;
	else if (get_time == 1'b1)
		data_sig_represent <= 16'h0;
	else if (get_time_d1 == 1'b1)
		data_sig_represent <= data_out;
	else
		data_sig_represent <= 16'hz;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		work_ok_represent <= 1'bz;
	else if (write_time == 1'b1)
		work_ok_represent <= 1'b0;
	else if (write_time_d1 == 1'b1)
		work_ok_represent <= 1'b1;
	else if (get_time == 1'b1)
		work_ok_represent <= 1'b0;
	else if (get_time_d1 == 1'b1)
		work_ok_represent <= 1'b1;
	else
		work_ok_represent <= 1'bz;

assign data_sig_inner = data_sig_represent;
assign work_ok_inner = work_ok_represent;

ram_256x16	ram_256x16_inst (
	.aclr ( ~sys_rst_n ),
	.address ( addr_buf ),
	.clock ( sys_clk ),
	.data ( data_buf ),
	.rden ( rd_en ),
	.wren ( wr_en ),
	.q ( data_out )
	);

endmodule